package android.slc.box.core.launcher;

import android.slc.box.core.controller.EventPlusHandler;
import android.slc.box.core.scope.IntentScope;
import android.slc.box.core.utils.WindowUtils;
import android.slc.box.core.virtual_android.Bundle;
import de.saxsys.mvvmfx.*;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.layout.Pane;
import javafx.stage.Window;
import javafx.stage.WindowEvent;
import org.apache.commons.lang3.ArrayUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public abstract class WindowLauncherImpl<T extends Window> implements WindowLauncher<T> {

    private final T window;
    private final List<String> stylesheets;
    private final Bundle bundle;
    private final EventPlusHandler onCloseEventHandler;
    private final ChangeListener<EventHandler<WindowEvent>> onCloseRequestProperty = new ChangeListener<EventHandler<WindowEvent>>() {
        @Override
        public void changed(ObservableValue<? extends EventHandler<WindowEvent>> observable, EventHandler<WindowEvent> oldValue, EventHandler<WindowEvent> newValue) {
            if (newValue == onCloseEventHandler) {
                return;
            }
            if (oldValue == onCloseEventHandler) {
                requireWindow().setOnCloseRequest(onCloseEventHandler);
            }
        }
    };

    public WindowLauncherImpl(T window, List<String> stylesheets, Bundle bundle) {
        this.window = window;
        this.stylesheets = stylesheets;
        this.bundle = bundle;
        this.onCloseEventHandler = WindowUtils.getOnWindowCloseRequest(this.getWindow());
        if (this.onCloseEventHandler != null) {
            requireWindow().onCloseRequestProperty().addListener(onCloseRequestProperty);
        }
    }

    @Override
    public List<String> getStylesheets() {
        return this.stylesheets;
    }

    @Override
    public Bundle getBundle() {
        return this.bundle;
    }

    @Override
    public T getWindow() {
        return this.window;
    }

    /**
     * 添加窗口关闭监听
     *
     * @param onWindowsCloseListener
     */
    @Override
    public void addOnWindowsCloseListener(EventPlusHandler.EventPlusHandlerListener onWindowsCloseListener) {
        this.onCloseEventHandler.addEventPlusHandlerListener(onWindowsCloseListener);
    }

    /**
     * 移除窗口关闭监听
     *
     * @param onWindowsCloseListener
     */
    @Override
    public void removeOnWindowsCloseListener(EventPlusHandler.EventPlusHandlerListener onWindowsCloseListener) {
        this.onCloseEventHandler.removeEventPlusHandlerListener(onWindowsCloseListener);
    }

    @Override
    public void addView(Pane parentPane, Parent contentView) {
        parentPane.getChildren().addAll(contentView);
    }

    @Override
    public <ViewType extends FxmlView<? extends ViewModelType>, ViewModelType extends ViewModel> Parent createView(Class<ViewType> viewClass, Bundle bundle, Scope... scopes) {
        ViewTuple<ViewType, ViewModelType> viewTuple = createViewTuple(viewClass, defineScopes(bundle, scopes));
        return viewTuple.getView();
    }

    @Override
    public <ViewType extends FxmlView<? extends ViewModelType>, ViewModelType extends ViewModel> ViewTuple<ViewType, ViewModelType> createViewTuple(Class<ViewType> viewClass, Collection<Scope> scopes) {
        ViewTuple<ViewType, ViewModelType> viewTuple = FluentViewLoader.fxmlView(viewClass).providedScopes(scopes).load();
        return viewTuple;
    }

    protected final List<Scope> defineScopes(Bundle bundle, Scope... scopes) {
        List<Scope> scopeList = new ArrayList<>();
        boolean isContainIntentScope = false;
        if (ArrayUtils.isNotEmpty(scopes)) {
            scopeList.addAll(Arrays.asList(scopes));
            //查找是否存在IntentScope
            for (Scope scope : scopes) {
                if (scope.getClass().equals(IntentScope.class)) {
                    //确保IntentScope数据
                    IntentScope intentScope = (IntentScope) scope;
                    if (intentScope.getStylesheets() == null) {
                        intentScope.setStylesheets(getStylesheets());
                    }
                    isContainIntentScope = true;
                    break;
                }
                //不用instanceof，不准确，需要排出子类
                /*if (scope instanceof IntentScope) {

                }*/
            }
        }
        if (!isContainIntentScope) {
            if (bundle == null) {
                bundle = new Bundle();
            }
            scopeList.add(new IntentScope(getStylesheets(), bundle));
        }
        return scopeList;
    }

    @Override
    public void destroyLauncher() {
        if (this.onCloseEventHandler != null) {
            requireWindow().onCloseRequestProperty().removeListener(onCloseRequestProperty);
        }
    }
}
